#include "CNode.h"
#include "CMessage.h"
#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <fstream>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CNode::CNode()
{
	t = NONE;
	busy = false;
}

CNode::CNode(int xloc, int yloc)
{
	//
	bw = 0.0001;
	x = xloc;
	y = yloc;
	ID = -1;
	busy = false;
}

CNode::CNode(CNode::Type type, int xMax, int yMax, int idNum)
{
	t = type;
	ID = idNum;
	busy = false;

	//Determine location. Randomized coordinate between 0,0 and xMax,yMax.
	x = randDouble(0., (double)xMax);
	y = randDouble(0., (double)yMax);

	//Give this node a connection bandwidth of some common figures (all in Mbps)
	//Numbers selected from common data connection estimated bw's
	//Not an accurate distribution of connection speeds.
	double speeds[] = {0.056, 0.256, 1.5, 3., 4., 20., 50.};
	int index = rand() % 7; //7 speeds listed above
	bw = speeds[index];

	compTime = 0.;
	totalData = 0.;
	comms = 0; 
}

CNode::~CNode()
{
	//deallocate resources
	for (int n=0; n<(int)neighbors.size(); n++)//NIter n=neighbors.begin(); n<neighbors.end(); n++)
	{
		//remove this node from their neighbor list
		//neighbors[n].otherNode->remN(this);
		remN(neighbors[n].otherNode);
	}
	for (int c=0; c<(int)neighbors.size(); c++)
	{
		//remove this node from their neighbor list
		//children[c].otherNode->remC(this);
		remN(neighbors[c].otherNode);
	}

	neighbors.clear();
	children.clear();
	files.clear();
	filesDesired.clear();
	dls.clear();
}

void CNode::Update(double time)
{
	if (!busy)
	{
		//Start a file request
		busy = true;
		CMessage newM(5);
		newM.addNode(this, bw);

		for (int g=0; g<(int)neighbors.size(); g++)
		{
			//
			comms++;
		}
	}
}

void CNode::newMessage(CMessage newM)
{
	//Process an incoming message
	for (int i=0; i<(int)files.size(); i++)
	{
		if (newM.getID() == files[i].ID)
			int e = 1;
	}
}



void CNode::remN(CNode* n)
{
	int q = 0;
	for(int i = 0; i < (int)neighbors.size(); i++) 
	{
		if (neighbors[i].otherNode == n)
		{
			//delete neighbors[i].otherNode;
			q = i;
		}
	}
	
	std::vector<connection>::iterator toDel = neighbors.begin() + q;
	neighbors.erase(toDel);
	return;
}

void CNode::remC(CNode* c)
{
	int q = 0;
	for(int i = 0; i < (int)children.size(); i++) 
	{
		if (children[i].otherNode == c)
		{
			//delete children[i].otherNode;
			q = i;
		}
	}
	std::vector<connection>::iterator toDel = children.begin() + q;
	children.erase(toDel);
	return;
}

void CNode::addN(CNode* n)
{
	connection con = connection(n);
	con.bw = std::min(n->getBW(), this->getBW());
	neighbors.push_back(con);
}

void CNode::addC(CNode* c)
{
	connection con = connection(c);
	con.bw = std::min(c->getBW(), this->getBW());
	neighbors.push_back(con);
}


void CNode::printData(std::string fname)
{
	std::ofstream file;
	file.open(fname.c_str(), std::ios::out | std::ios::app);
	if (file.is_open())
	{
		file << ID << "," << bw << "," << compTime << "," << totalData << "," 
			<< comms << "," << neighbors.size() << "," << children.size() << "," 
			<< x << "," << y << std::endl;

		/*file << "    Node " << ID << " (" << t << ") :" << std::endl;
		file << "       Bandwidth: " << bw << " Mbps" << std::endl;
		file << "       Total computation time: " << compTime << " sec" << std::endl;
		file << "       Total data transferred: " << totalData << " Mb" << std::endl;
		file << "       Total communications: " << comms << std::endl << std::endl;*/
		
		file.close();
	}
}


double CNode::getDist(double someX, double someY)
{
	double xdif = (x < someX) ? (someX - x) : (x - someX);
	double ydif = (y < someY) ? (someY - y) : (y - someY);

	return xdif + ydif;
}